看這段代碼:
function getFullName(user) {
return `${user.firstName} ${user.lastName}`;
}
表面上很直觀對吧?從 user 物件拿 firstName 和 lastName。但壞消息來了,假如後端某天改成傳 first
和 last
,你就得重寫整個函數。這樣緊耦合的代碼根本沒有得到函數該有的好處,還違反了 open-close principle。
那不如這樣寫:
// 類別
class User {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
getFullName() {
return `${this.firstName} ${this.lastName}`;
}
}
// 函數
function getFullName({firstName, lastName}) {
return `${firstName} ${lastName}`;
}
你看,建構子不再綁死特定的資料結構了。這樣的設計很自然,不管外面的資料長什麼樣子,User 類別都能處理。我們來看看這種「解放」的威力:
// 類別初始
const customer = new User(user.first, user.last);
const customer = new User(product.user.firstName, product.user.lastName);
const customer = new User(response.data.givenName, response.data.familyName);
customer.getFullName()
// 函數
getFullName({firstName: user.first, lastName: user.last})
getFullName({firstName: product.user.firstName, lastName: product.user.lastName})
getFullName({firstName: response.data.givenName, lastName: response.data.familyName})
function 真的應該避免跟特定結構綁在一起。讓呼叫方去處理資料轉換,你的介面就能保持穩定。這樣做有幾個好處:介面不會因為外部資料格式變動而改變、同一個類別可以重複使用在不同資料來源、建構子專心做自己的事情就好、測試時也不用搞一堆複雜的假資料。
所以說,愛不是束縛而是解放 — — 程式設計也是一樣,讓你的函數從資料結構的束縛中解放出來,才能獲得真正的靈活性。